#pragma once

#ifndef FACTORY_H_
#define FACTORY_H_

#include <iostream>
#include <list>
#include <string>
#include <cstdlib>
using namespace std;


//base class for all kind of pizzas
class Pizza
{
public:
	Pizza()
	{

	}
	virtual ~Pizza()
	{

	}

	virtual void prepare()=0;
	void bake()
	{
		//TRACE("baking\n");
		cout<<"baking"<<endl;
	}
	void cut()
	{
		//TRACE("cutting\n");
		cout<<"cutting"<<endl;
	}
	void box() 
	{ //TRACE("boxing\n"); 
		cout<<"boxing"<<endl;
	}
};
//an interface for order all kinds of pizzas
class PizzaStore
{
public:
	PizzaStore()
	{

	}
	virtual ~PizzaStore()
	{

	}

	Pizza* OrderPizza(string type)
	{
		Pizza* pizza;
		pizza = createPizza(type);
		pizza->prepare();
		pizza->bake();
		pizza->cut();
		pizza->box();

		return pizza;

	}

	virtual Pizza* createPizza(string type)=0;

};

enum DOUGHTYPE{ THICKCRUST, THINCRUST};

class Dough
{
public:
	Dough()
	{

	}
	virtual ~Dough()
	{

	}
	virtual int getDoughtype()=0;
};

class ThickCrustDough:public Dough
{
public:
	ThickCrustDough()
	{

	}
	virtual ~ThickCrustDough()
	{

	}

	int getDoughtype()
	{
		return THICKCRUST;
	}
};

class ThinCrustDough:public Dough
{
public:
	ThinCrustDough()
	{

	}
	virtual ~ThinCrustDough()
	{

	}

	int getDoughtype()
	{
		return THINCRUST;
	}
};

//interface for Ingredient factory
class IngredientFactory
{
public:
	IngredientFactory()
	{

	}
	virtual ~IngredientFactory()
	{

	}

	virtual Dough* createDough()=0;
};

class NyIngredientFactory: public IngredientFactory
{
public:
	NyIngredientFactory()
	{
		cout<<"NyIngredientFactroy created\n";
	}
	virtual ~NyIngredientFactory()
	{

	}

	Dough* createDough()
	{
		Dough* pDough = new ThinCrustDough();
		return pDough;
	}
};

class ChIngredientFactory:public IngredientFactory
{
public:
	ChIngredientFactory()
	{
		cout<<"ChIngredientFactory created\n";
	}
	virtual ~ChIngredientFactory()
	{

	}

	Dough* createDough()
	{
		Dough *pdough = new ThickCrustDough();
		return pdough;
	}
};

class cheesePizza:public Pizza
{
public:
	cheesePizza(IngredientFactory* inf):_dough(NULL),_ingredientFactory(inf)
	{
		
	}
	virtual ~cheesePizza()
	{

	}

	void prepare()
	{
		_dough = _ingredientFactory->createDough();
		cout<<_dough->getDoughtype()<<" type of dough created\n";

		
	}

private:
	Dough*  _dough;
	IngredientFactory*  _ingredientFactory;

};

class clamPizza:public Pizza
{
public:
	clamPizza(IngredientFactory* inf):_dough(NULL),_ingredientFactory(inf)
	{

	}
	virtual ~clamPizza() {}

	void prepare()
	{
		_dough = _ingredientFactory->createDough();
		cout<<_dough->getDoughtype()<<" type of dough created\n";
	}

private:
	Dough* _dough;
	IngredientFactory* _ingredientFactory;
};


#endif